
#include "touchInput.h"
#include "rect.h"

CTouchInput::CTouchInput( void )
{
	m_Event = TOEV_INVALID;
	m_NumInputs = 0;
	m_NoAcceleromterInfo = TRUE;
	m_Shake = FALSE;
	m_Shakes = 0;
	m_RaiseUp = FALSE;
	m_DownTime = m_UpTime = 0;
	
	m_Accelerometer0[0] = 0;
	m_Accelerometer0[1] = 0;
	m_Accelerometer0[2] = 0;
	
	m_Accelerometer1[0] = 0;
	m_Accelerometer1[1] = 0;
	m_Accelerometer1[2] = 0;
}

void CTouchInput::HandleEvent( TouchEvent event, const vec2 * pPosition, long time, int taps, int numInputs )
{	
	m_Event = event;
	m_LastPosition = m_Position;
	m_Position = *pPosition;
	m_Taps = taps;
	m_NumInputs = numInputs;

	if( event == TOEV_UP )
	{
		m_UpTime = time;
	}
	else if( event == TOEV_DOWN )
	{
		m_DownTime = time;
		m_LastPosition = m_DownPos = *pPosition;
		m_Velocity.Clear();
	}
	else if( event == TOEV_MOVE )
	{
		m_Velocity = m_Position - m_LastPosition;
	}
}

#define kFilteringFactor			0.1

void CTouchInput::HandleAccelerometer( float x, float y, float z )
{
	m_lastAccelX = m_curAccelX;
	m_lastAccelY = m_curAccelY;
	m_lastAccelZ = m_curAccelZ;
	
	m_curAccelX = x;
	m_curAccelY = y;
	m_curAccelZ = z;
	
	if( m_NoAcceleromterInfo )
	{
		m_Accelerometer0[0] = x;
		m_Accelerometer0[1] = y;
		m_Accelerometer0[2] = z;
		m_Accelerometer1[0] = x;
		m_Accelerometer1[1] = y;
		m_Accelerometer1[2] = z;
		
		m_NoAcceleromterInfo = FALSE;
	}
	else
	{
		//Use a basic low-pass filter to only keep the gravity in the accelerometer values
		m_Accelerometer1[0] = ( x - ( x * kFilteringFactor + m_Accelerometer1[0] * (1.0 - kFilteringFactor) ) ) / 3;
		m_Accelerometer1[1] = ( y - ( y * kFilteringFactor + m_Accelerometer1[1] * (1.0 - kFilteringFactor) ) ) / 3;
		m_Accelerometer1[2] = ( z - ( z * kFilteringFactor + m_Accelerometer1[2] * (1.0 - kFilteringFactor) ) ) / 3;
		
		float delta[3];
		delta[0] = m_Accelerometer1[0] - m_Accelerometer0[0];
		delta[1] = m_Accelerometer1[1] - m_Accelerometer0[1];
		delta[2] = m_Accelerometer1[2] - m_Accelerometer0[2];
		
		int max = 0;
		
		// get the maximum delta
		if( fabs( delta[1] ) > fabs( delta[0] ) )
			max = 1;
		if( fabs( delta[2] ) > fabs( delta[max] ) )
			max = 2;
		
		// check for any spikes in the accelerometer
		if( fabs( delta[max] ) > .4 )
		{
			++m_Shakes;
			
			m_Accelerometer0[0] = m_Accelerometer1[0];
			m_Accelerometer0[1] = m_Accelerometer1[1];
			m_Accelerometer0[2] = m_Accelerometer1[2];
			
			// detect the number of movements to detect a shake
			if( m_Shakes >= 1 ) // 10 )
			{
				m_Shake = TRUE;
				m_Shakes = 0;
			}
		}
		
		if (/*m_curAccelZ > 0 && m_lastAccelZ < 0 && */fabs(m_lastAccelZ - m_curAccelZ) > 1.5)
		{
			m_RaiseUp = TRUE;
		}
	}
}

void CTouchInput::Reset()
{
	if( m_Event == TOEV_UP)
	{
		m_DownTime = m_UpTime = 0;
		m_DownPos.Clear();
		m_Position.Clear();
		m_LastPosition.Clear();
		m_Velocity.Clear();
	}
	
	m_Event = TOEV_INVALID;
	m_Taps = 0;
	m_Shake = FALSE;
	m_RaiseUp = FALSE;
}

void CTouchInput::Clear()
{
	Reset();
	m_Velocity.Clear();
	m_Event = TOEV_CLEAR;
}

boolean CTouchInput::HitsRect( const _Rect * pRect ) const
{ // TOEV_UP
	if( m_Event == TOEV_UP && 
	   fabs(m_DownPos.x.Int16() - m_Position.x.Int16()) < 20 && 
	   fabs(m_DownPos.y.Int16() - m_Position.y.Int16()) < 20
	   )
	{
		return pRect->Contains( m_Position.x.Int16(), m_Position.y.Int16() );
	}
	
	return FALSE;
}

boolean CTouchInput::PressRect( const _Rect * pRect ) const
{ // TOEV_DOWN & TOEV_MOVE
	if( m_DownTime && !m_UpTime && m_Event != TOEV_CLEAR )
	{
		return pRect->Contains( m_Position.x.Int16(), m_Position.y.Int16() );
	}
	
	return FALSE;
}

boolean CTouchInput::IsOverTurn()
{
	// printf("\nlastZ:%d, curZ:%d, lastX:%d, curX:%d",m_lastAccelZ,m_curAccelZ,m_lastAccelX,m_curAccelX);
	if (m_lastAccelZ < 0 && m_curAccelZ > 0 )
		return true;
	else
		return false;
}

